---
title: Create pages with Expo Router
description: Learn about the file-based routing convention used by Expo Router.
sidebar_title: Create pages
---

import { FileTree } from '~/ui/components/FileTree';
import { Tabs, Tab } from '~/ui/components/Tabs';

When a file is created in the **app** directory, it automatically becomes a route in the app. For example, the following files will create the following routes:

<FileTree
  files={[
    ['app/index.tsx', "matches '/'"],
    ['app/home.tsx', "matches '/home'"],
    ['app/[user].tsx', "matches dynamic paths like '/expo' or '/evanbacon'"],
    ['app/settings/index.tsx', "matches '/settings'"],
  ]}
/>

## Pages

Pages are defined by exporting a React component as the default value from a file in the **app** directory. The file they are exported from must use one of the `.js`, `.jsx`, `.tsx`, `.ts` extensions.

For example, create the **app** directory in your project and then create a file **index.tsx** inside it. Then, add the following snippet:

<Tabs>

<Tab label="Universal">

    Render text on any platform with the `<Text>` component from React Native.

    ```tsx app/index.tsx
    import { Text } from 'react-native';

    export default function Page() {
      return <Text>Top-level page</Text>;
    }
    ```

</Tab>

<Tab label="Web-only">

    Alternatively, you can write web-only React components such as `<div>`, `<p>`, and so on. However, these won't render on native platforms.

    ```tsx app/index.tsx
    export default function Page() {
      return <p>Top-level page</p>;
    }
    ```

</Tab>

</Tabs>

The above example matches the `/` route in the app and the browser. Files named **index** match the parent directory and do not add a path segment. For example, **app/settings/index.tsx** matches `/settings` in the app.

## Platform specific extensions

> **warning** Platform-specific extensions were added in Expo Router `3.5.x`. If you are using an older version of the library, follow instructions from [Platform-specific modules](/router/advanced/platform-specific-modules).

Metro bundler's platform-specific extensions (for example, **.ios.tsx** or **.native.tsx**) are supported in the **app** directory only if a **non-platform version** also exists. This ensures that routes are universal across platforms for deep linking.

Consider the following project structure:

<FileTree
  files={[
    'app/_layout.tsx',
    'app/_layout.web.tsx',
    'app/index.tsx',
    'app/about.tsx',
    'app/about.web.tsx',
  ]}
/>

In the above file structure:

- **\_layout.web.tsx** file is used as a layout on the web and **\_layout.tsx** is used on all other platforms.
- **index.tsx** file is used as the home page for all platforms.
- **about.web.tsx** file is used as the about page for the web, and the **about.tsx** file is used on all other platforms.

> **info** Providing a route file without a platform-specific extension is required to ensure every platform has a default implementation.

## Dynamic routes

Dynamic routes match any unmatched path at a given segment level.

| Route                      | Matched URL          |
| -------------------------- | -------------------- |
| **app/blog/[slug].tsx**    | `/blog/123`          |
| **app/blog/[...rest].tsx** | `/blog/123/settings` |

Routes with higher specificity will be matched before a dynamic route. For example, `/blog/bacon` will match **blog/bacon.tsx** before **blog/[id].tsx**.

Multiple slugs can be matched in a single route by using the rest syntax (`...`). For example, **app/blog/[...id].tsx** matches `/blog/123/settings`.

Dynamic segments are accessible as [route parameters](/router/reference/url-parameters) in the page component.

{/* prettier-ignore */}
```tsx app/blog/[slug].tsx
/* @info Import the <b>useLocalSearchParams</b> React hook */
import { useLocalSearchParams } from 'expo-router';
/* @end */
import { Text } from 'react-native';

export default function Page() {
  /* @info Access the query parameter named <b>slug</b> */
  const { slug } = useLocalSearchParams();
  /* @end */

  return <Text>Blog post: {slug}</Text>;
}
```
